#include <log4cxx/logger.h>
#include <json/json.h>

#include <MetadataSvrCommon.h>


#include "MetadataSvrClientProtoHelper.h"
#include "MetadataSvrClient.h"


static LoggerPtr g_logger = Logger::getLogger("MetadataSvrClientProtoHelper");

string mds_build_request_create_md_file(int32_t dir_id, int64_t file_id) {
	if (dir_id < 0 || file_id < 0) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", invalid args");
                return "";
        }
        json_object * j = json_object_new_object();
        json_object * j_cmd_id = json_object_new_int(MDS_CMD_CREATE_MD_FILE);
        json_object * j_dir_id = json_object_new_int(dir_id);
        json_object * j_file_id = json_object_new_int(file_id);
        json_object_object_add(j, "CMD_ID", j_cmd_id);
        json_object_object_add(j, "DIR_ID", j_dir_id);
        json_object_object_add(j, "FILE_ID", j_file_id);
        string request = json_object_to_json_string(j);
        json_object_put(j);
        return request;
}


string mds_build_request_delete_md_file(int32_t dir_id, int64_t file_id) {
	if (dir_id < 0 || file_id < 0) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", invalid args");
                return "";
        }
        json_object * j = json_object_new_object();
        json_object * j_cmd_id = json_object_new_int(MDS_CMD_DELETE_MD_FILE);
        json_object * j_dir_id = json_object_new_int(dir_id);
        json_object * j_file_id = json_object_new_int(file_id);
        json_object_object_add(j, "CMD_ID", j_cmd_id);
        json_object_object_add(j, "DIR_ID", j_dir_id);
        json_object_object_add(j, "FILE_ID", j_file_id);
        string request = json_object_to_json_string(j);
        json_object_put(j);
        return request;
}


string mds_build_request_get_md_file_info(int32_t dir_id, int64_t file_id) {
	if (dir_id < 0 || file_id < 0) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", invalid args");
                return "";
        }
        json_object * j = json_object_new_object();
        json_object * j_cmd_id = json_object_new_int(MDS_CMD_GET_MD_FILE_INFO);
        json_object * j_dir_id = json_object_new_int(dir_id);
        json_object * j_file_id = json_object_new_int(file_id);
        json_object_object_add(j, "CMD_ID", j_cmd_id);
        json_object_object_add(j, "DIR_ID", j_dir_id);
        json_object_object_add(j, "FILE_ID", j_file_id);
        string request = json_object_to_json_string(j);
        json_object_put(j);
        return request;

}

string mds_build_request_data_svr_notify_data_file_info(int32_t dir_id, int64_t file_id, int data_svr_id, int64_t file_size, \
							vector<uint32_t> crcs, int delete_flag, int notify_reason) {
	if (dir_id < 0 || file_id < 0 || data_svr_id < 0) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", invalid args, dir_id:" << dir_id << ", file_id:" << file_id << \
				", data_svr_id:" << data_svr_id);
                return "";
        }
        json_object * j = json_object_new_object();
        json_object * j_cmd_id = json_object_new_int(MDS_CMD_DATA_SVR_NOTIFY_DATA_FILE_INFO);
        json_object * j_dir_id = json_object_new_int(dir_id);
        json_object * j_file_id = json_object_new_int(file_id);
        json_object * j_data_svr_id = json_object_new_int(data_svr_id);
        json_object * j_file_size = json_object_new_int(file_size);
        json_object * j_crcs = json_object_new_array();
        json_object * j_delete_flag = json_object_new_int(delete_flag); 
        json_object * j_notify_reason = json_object_new_int(notify_reason); 
	 for(vector<uint32_t>::const_iterator iter = crcs.begin(); crcs.end() != iter; iter++) {
                json_object * j_crc = json_object_new_int(*iter);
                json_object_array_add(j_crcs, j_crc);
        }
        json_object_object_add(j, "CMD_ID", j_cmd_id);
        json_object_object_add(j, "DIR_ID", j_dir_id);
        json_object_object_add(j, "FILE_ID", j_file_id);
        json_object_object_add(j, "DATA_SVR_ID", j_data_svr_id);
        json_object_object_add(j, "FILE_SIZE", j_file_size);
        json_object_object_add(j, "CRC", j_crcs);
        json_object_object_add(j, "DELETE_FLAG", j_delete_flag);
        json_object_object_add(j, "NOTIFY_REASON", j_notify_reason);
        string request = json_object_to_json_string(j);
        json_object_put(j);
        return request;

}

string mds_build_request_client_notify_client_data_info(int32_t dir_id, int64_t file_id, vector<uint32_t> crcs) {
	if (dir_id < 0 || file_id < 0 ) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", invalid args");
                return "";
        }
        json_object * j = json_object_new_object();
        json_object * j_cmd_id = json_object_new_int(MDS_CMD_CLIENT_NOTIFY_CLIENT_DATA_INFO);
        json_object * j_dir_id = json_object_new_int(dir_id);
        json_object * j_file_id = json_object_new_int(file_id);
        json_object * j_crcs = json_object_new_array();
	 for(vector<uint32_t>::const_iterator iter = crcs.begin(); crcs.end() != iter; iter++) {
                json_object * j_crc = json_object_new_int(*iter);
                json_object_array_add(j_crcs, j_crc);
        }
        json_object_object_add(j, "CMD_ID", j_cmd_id);
        json_object_object_add(j, "DIR_ID", j_dir_id);
        json_object_object_add(j, "FILE_ID", j_file_id);
        json_object_object_add(j, "CRC", j_crcs);
        string request = json_object_to_json_string(j);
        json_object_put(j);
        return request;

}

string mds_build_request_alloc_ds_4_new_file() {
        json_object * j = json_object_new_object();
        json_object * j_cmd_id = json_object_new_int(MDS_CMD_ALLOC_DS_4_NEW_FILE);
        json_object_object_add(j, "CMD_ID", j_cmd_id);
        string request = json_object_to_json_string(j);
        json_object_put(j);
        return request;


}

int mds_parse_response_create_md_file(const char * response, int & result) {
        if (NULL == response) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", invalid args");
                return -1;
        }
        json_object * j = json_tokener_parse(response);
        if (is_error(j)) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ",  parse response err:" << response);
                return -2;
        }
        json_object * j_result = json_object_object_get(j, "RESULT");
        if (is_error(j_result)) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", no RESULT found in response:" << response);
                json_object_put(j);
                return -3;
        }
        result = json_object_get_int(j_result);
        json_object_put(j);
        return 1;
}

int mds_parse_response_delete_md_file(const char * response, int & result) {
        if (NULL == response) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", invalid args");
                return -1;
        }
        json_object * j = json_tokener_parse(response);
        if (is_error(j)) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ",  parse response err:" << response);
                return -2;
        }
        json_object * j_result = json_object_object_get(j, "RESULT");
        if (is_error(j_result)) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", no RESULT found in response:" << response);
                json_object_put(j);
                return -3;
        }
        result = json_object_get_int(j_result);
        json_object_put(j);
        return 1;
}

int mds_parse_response_get_md_file_info(const char * response, int & result, MD_FILE_INFO & info) {
        if (NULL == response) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", invalid args");
                return -1;
        }
        json_object * j = json_tokener_parse(response);
        if (is_error(j)) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ",  parse response err:" << response);
                return -2;
        }
        json_object * j_result = json_object_object_get(j, "RESULT");
        if (is_error(j_result)) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", no RESULT found in response:" << response);
                json_object_put(j);
                return -3;
        }
	json_object * j_client_md_record = json_object_object_get(j, "CLIENT_MD_RECORD");
        if (is_error(j_client_md_record)) {
                LOG4CXX_WARN(g_logger, __FUNCTION__ << ", no client metadata record found in response:" << response);
        }
	else {
		json_object * j_client_crcs = json_object_object_get(j_client_md_record, "CLIENT_CRC");
		if (NULL == j_client_crcs || is_error(j_client_crcs)) {
			LOG4CXX_WARN(g_logger, __FUNCTION__ << ", no client crc info in client medadata record");
		}
		else {
			for(int i=0; i < json_object_array_length(j_client_crcs); i++) {
				json_object * j_t = json_object_array_get_idx(j_client_crcs, i);
				info.client_md_record.crcs.push_back(json_object_get_int(j_t));
			}
		}
	}
	json_object * j_data_svr_md_records = json_object_object_get(j, "DATA_SVR_MD_RECORDS");
        if (NULL == j_data_svr_md_records || is_error(j_data_svr_md_records)) {
                LOG4CXX_WARN(g_logger, __FUNCTION__ << ", no data svr metadata records found in response:" << response);
        }
	else {
		for(int i=0; i < json_object_array_length(j_data_svr_md_records); i++) {
			json_object * j_data_svr_md_record = json_object_array_get_idx(j_data_svr_md_records, i);
			json_object * j_data_svr_id = json_object_object_get(j_data_svr_md_record, "DATA_SVR_ID");
			json_object * j_file_size = json_object_object_get(j_data_svr_md_record, "FILE_SIZE");
			json_object * j_data_svr_crcs = json_object_object_get(j_data_svr_md_record, "CRC");
			DATA_SVR_MD_RECORD r;
			int data_svr_id = json_object_get_int(j_data_svr_id);
			r.file_size = json_object_get_int(j_file_size);
			for(int j=0; j < json_object_array_length(j_data_svr_crcs); j++) {
				json_object * j_crc = json_object_array_get_idx(j_data_svr_crcs, j);
				r.crcs.push_back(json_object_get_int(j_crc));
			}
			info.data_svr_md_records.insert(map<int, DATA_SVR_MD_RECORD>::value_type(data_svr_id, r));
		}
	}
	result = json_object_get_int(j_result);
        json_object_put(j);
        return 1;
}

int mds_parse_response_data_svr_notify_data_file_info(const char * response, int & result) {
        if (NULL == response) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", invalid args");
                return -1;
        }
        json_object * j = json_tokener_parse(response);
        if (is_error(j)) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ",  parse response err:" << response);
                return -2;
        }
        json_object * j_result = json_object_object_get(j, "RESULT");
        if (is_error(j_result)) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", no RESULT found in response:" << response);
                json_object_put(j);
                return -3;
        }
        result = json_object_get_int(j_result);
        json_object_put(j);
        return 1;
}

int mds_parse_response_client_notify_client_data_info(const char * response, int & result) {
        if (NULL == response) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", invalid args");
                return -1;
        }
        json_object * j = json_tokener_parse(response);
        if (is_error(j)) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ",  parse response err:" << response);
                return -2;
        }
        json_object * j_result = json_object_object_get(j, "RESULT");
        if (is_error(j_result)) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", no RESULT found in response:" << response);
                json_object_put(j);
                return -3;
        }
        result = json_object_get_int(j_result);
        json_object_put(j);
        return 1;
}

int mds_parse_response_alloc_ds_4_new_file(const char * response, int & result, int32_t & ds_id, int32_t & dir_id, \
						int64_t & file_id) {
        if (NULL == response) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", invalid args");
                return -1;
        }
        json_object * j = json_tokener_parse(response);
        if (is_error(j)) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ",  parse response err:" << response);
                return -2;
        }
        json_object * j_result = json_object_object_get(j, "RESULT");
        json_object * j_ds_id = json_object_object_get(j, "DS_ID");
        json_object * j_dir_id = json_object_object_get(j, "DIR_ID");
        json_object * j_file_id = json_object_object_get(j, "FILE_ID");
        if (NULL == j_result) {
                LOG4CXX_ERROR(g_logger, __FUNCTION__ << ", no RESULT found in response:" << response);
                json_object_put(j);
                return -3;
        }
        result = json_object_get_int(j_result);
        ds_id = json_object_get_int(j_ds_id);
        dir_id = json_object_get_int(j_dir_id);
        file_id = json_object_get_int(j_file_id);
        json_object_put(j);
        return 1;
}
